﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WastedMechanics
{
    public class SoundEffect
    {
        public FMOD.Sound FmodSound;        
        public string FileName;
        public bool Is3D;

        public Queue<FMOD.Channel> UsedChannels;

        public SoundEffect(string fileName, bool is3d)
        {
            FileName = Engine.GetResourcePath(fileName);
            UsedChannels = new Queue<FMOD.Channel>();
            Is3D = is3d;
        }

        public void Load()
        {
            if (FmodSound == null)
            {
                FMOD.RESULT result = Engine.SoundManager.FmodSystem.createSound(
                    FileName, FMOD.MODE.HARDWARE | (Is3D ? FMOD.MODE._3D : FMOD.MODE._2D), ref FmodSound);
                Engine.SoundManager.FmodERRCHECK(result);
            }
        }

        public SoundInstance PlayNewInstance(bool loop=false)
        {
            if (loop)
                FmodSound.setMode(FMOD.MODE.LOOP_NORMAL);
            else
                FmodSound.setMode(FMOD.MODE.LOOP_OFF);

            FMOD.Channel channel = Engine.SoundManager.GetFreeChannel();
            bool reuse = false;
            if (channel == null && UsedChannels.Count != 0)
            {
                channel = UsedChannels.Dequeue();
                reuse = true;
            }
            if (channel != null)
            {
                UsedChannels.Enqueue(channel);

                if (reuse)
                    Engine.SoundManager.FmodSystem.playSound(FMOD.CHANNELINDEX.REUSE, FmodSound, false, ref channel);
                else
                    Engine.SoundManager.FmodSystem.playSound(FMOD.CHANNELINDEX.FREE, FmodSound, false, ref channel);
                return new SoundInstance(this, loop, channel);
            }
            else
                return new SoundInstance(this, false, null);
        }

        public void StopAll()
        {
            while (UsedChannels.Count != 0)
                UsedChannels.Dequeue().stop();            
        }
        

        public void Unload()
        {
            if (FmodSound != null)
            {
                FmodSound.release();
                FmodSound = null;
            }            
        }

        public void SetMinMaxDistance(float min, float max)
        {
            FmodSound.set3DMinMaxDistance(min, max);
        }

        public float Length
        {
            get
            {                
                uint len = 0;
                if (FmodSound != null)
                    FmodSound.getLength(ref len, FMOD.TIMEUNIT.MS);
                return (float)len / 1000.0f;
            }
        }
    }
}
